package com.vimhe.easyimport;

import com.vimhe.easyimport.config.ImportConfig;
import com.vimhe.easyimport.filter.DataFilter;
import com.vimhe.easyimport.filter.DataFilterChain;
import com.vimhe.easyimport.processor.DataProcessor;
import com.vimhe.easyimport.reader.ExcelFormat;
import com.vimhe.easyimport.reader.ExcelReader;
import com.vimhe.easyimport.reader.IExcelReader;
import com.vimhe.easyimport.util.ExcelReaderUtil;
import com.vimhe.easyimport.validate.DataValidator;
import com.vimhe.easyimport.validate.DataValidatorChain;
import com.vimhe.easyimport.validate.ErrorMessageResolver;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.xml.sax.SAXException;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/**
 * 数据导入管理器
 *
 * @author Vimhe
 */
public class ImportManager {

    /**
     * 文件格式“xls或xlsx”
     */
    private ExcelFormat excelFormat;

    /**
     * 文件输入流
     */
    private InputStream inputStream;

    /**
     * Excel解析器接口
     */
    private IExcelReader excelReader;

    public ImportManager(ImportConfig importConfig,
                         String fileName,
                         ExcelFormat excelFormat,
                         InputStream inputStream,
                         DataValidatorChain validatorChain,
                         ErrorMessageResolver messageResolver,
                         DataFilterChain filterChain,
                         DataProcessor processor) {
        this.excelFormat = excelFormat;
        this.inputStream = inputStream;

        excelReader = new ExcelReader(fileName, importConfig, validatorChain, messageResolver, filterChain, processor);
    }

    public static Builder builder() {
        return new Builder();
    }

    /**
     * 开始解析
     *
     * @throws IOException        e
     * @throws SAXException       e
     * @throws OpenXML4JException e
     */
    public void run() throws IOException, SAXException, OpenXML4JException {
        ExcelReaderUtil.readExcel(excelReader, excelFormat, inputStream);
    }

    public static final class Builder {
        private ImportConfig importConfig;
        private String fileName;
        private ExcelFormat excelFormat;
        private InputStream inputStream;
        private DataValidatorChain validatorChain;
        private ErrorMessageResolver messageResolver;
        private DataFilterChain filterChain;
        private DataProcessor processor;

        public Builder setImportConfig(ImportConfig importConfig) {
            this.importConfig = importConfig;
            return this;
        }

        public Builder setFilePath(String filePath) throws FileNotFoundException {
            String suffix = filePath.substring(filePath.lastIndexOf('.') + 1).toUpperCase();
            setExcelFormat(ExcelFormat.valueOf(suffix));
            setInputStream(new FileInputStream(filePath));
            return this;
        }

        public Builder setFileName(String fileName) {
            this.fileName = fileName;
            return this;
        }

        public Builder setExcelFormat(ExcelFormat excelFormat) {
            this.excelFormat = excelFormat;
            return this;
        }

        public Builder setInputStream(InputStream inputStream) {
            this.inputStream = inputStream;
            return this;
        }

        public Builder addDataValidator(DataValidator dataValidator) {
            if (validatorChain == null) {
                validatorChain = new DataValidatorChain();
            }

            this.validatorChain.addValidator(dataValidator);
            return this;
        }

        public Builder setErrorMessageResolver(ErrorMessageResolver messageResolver) {
            this.messageResolver = messageResolver;
            return this;
        }

        public Builder addDataFilter(DataFilter dataFilter) {
            if (filterChain == null) {
                filterChain = new DataFilterChain();
            }

            this.filterChain.addFilter(dataFilter);
            return this;
        }

        public Builder addDataProcessor(DataProcessor dataProcessor) {
            this.processor = dataProcessor;
            return this;
        }

        public ImportManager build() {
            return new ImportManager(this.importConfig,
                    this.fileName,
                    this.excelFormat,
                    this.inputStream,
                    this.validatorChain,
                    this.messageResolver,
                    this.filterChain,
                    this.processor);
        }
    }

}
